package com.shimao.celnet.payment.controller.api;

import com.shimao.celnet.payment.model.PPay;
import com.shimao.celnet.payment.model.PPayCust;
import com.shimao.celnet.payment.model.PPayRefund;
import com.shimao.celnet.payment.model.request.CallIn_OutPayReqInRequest;
import com.shimao.celnet.payment.model.response.ErrorInfoEnum;
import com.shimao.celnet.payment.model.response.ResponseJson;
import com.shimao.celnet.payment.service.PPayCupUserService;
import com.shimao.celnet.payment.service.PPayCustService;
import com.shimao.celnet.payment.service.PPayRefundService;
import com.shimao.celnet.payment.service.PPayService;
import com.shimao.celnet.payment.service.impl.apiservice.CallOut_TLPublicService;
import com.shimao.celnet.payment.util.FinalUtil;
import com.shimao.celnet.payment.util.MyDateUtil;
import io.swagger.annotations.Api;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

/**
 * 支付撤销或退款接口
 * 外部系统 → 支付系统，数据：撤销或退款数据
 * 支持部分金额退款
 * Created by Galen on 2018/11/23.
 */
@RestController
@RequestMapping(value = "/payment")
@Api("接口：pay-209(银联)-外部撤销或退款<OutPayCancelOrRefundReqIn> 外部系统 → 支付系统，数据：撤销或退款数据")
public class CallIn_OutPayCancelOrRefundReqInController {
    protected Logger logger = Logger.getLogger(this.getClass());

    @Autowired
    private PPayCustService pPayCustService;

    @Autowired
    private CallOut_TLPublicService callOut_tlPublicService;

    @Autowired
    private PPayCupUserService pPayCupUserService;

    @Autowired//支付申请
    private PPayService pPayService;

    @Autowired
    private PPayRefundService pPayRefundService;

    @RequestMapping(value = "/payCancelOrRefundReq", method = RequestMethod.POST)
    public String outPayCancelOrRefundReq(@RequestBody CallIn_OutPayReqInRequest requestJson) {
        ResponseJson retJson = new ResponseJson(ErrorInfoEnum.SUCCESS, "");
        logger.info("pay-209(银联)-外部撤销或退款<OutPayCancelOrRefundReqIn>请求JSON:" + requestJson.toString());
        if (StringUtils.isEmpty(requestJson.getPaymentId())) {
            logger.debug("缺少必要参数：" + requestJson.getPaymentId());
            retJson = new ResponseJson(ErrorInfoEnum.NOT_PARAMS, "paymentId");
            return retJson.toString();
        }
        if (StringUtils.isEmpty(requestJson.getRefundAmount())) {
            logger.debug("缺少必要参数：" + requestJson.getPaymentId());
            retJson = new ResponseJson(ErrorInfoEnum.NOT_PARAMS, "paymentId");
            return retJson.toString();
        } else if (Long.valueOf(requestJson.getRefundAmount()) < 0) {
            retJson = new ResponseJson(ErrorInfoEnum.ERROR_PARAMS, "refundAmount:" + requestJson.getRefundAmount());
            logger.debug("请求金额异常：" + requestJson.getRefundAmount());
            return retJson.toString();
        }
        //根据guid查询数据库中的账单表
        PPay pPay = pPayService.getByKey(requestJson.getPaymentId());
        if (pPay == null) {
            retJson = new ResponseJson(ErrorInfoEnum.ERROR_PARAMS, "meruserid");
            return retJson.toString();
        }
        PPayCust pPayCust = getTLMessage(pPay.getEstateGuid(), pPay.getPayType());
        PPayRefund pPayRefund = pPayRefundService.selectListByMap(requestJson.getPaymentId());
        //如果该支付订单已退款，就不能再进行退款
        if (pPayRefund != null && FinalUtil.PAY_REFUND_SUCCESS.equals(pPayRefund.getRefundStatus()) && pPayRefund.getRefundAmount().equals(requestJson.getRefundAmount())) {
            retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, "该订单已经执行过退款！");
            return retJson.toString();
        }
        //==========退款请求金额等于订单总额 & 小于订单总额==========
        if (Integer.valueOf(pPay.getPayAmount()) - Integer.valueOf(requestJson.getRefundAmount()) >= 0) {
            //==================交易日期在当天内，并且退款金额与支付金额相同============
            String refundAmount = requestJson.getRefundAmount();
            pPay.setRefundAmount(refundAmount);
            if (MyDateUtil.isThisTime(Long.valueOf(pPay.getPayEndTime()), MyDateUtil.format_yyyy_MM_dd) && Integer.valueOf(pPay.getPayAmount()) - Integer.valueOf(refundAmount) == 0) {
                //================通联撤销处理：保存撤销数据==================
                logger.info("================请求金额通联撤销开始================");
                PPayRefund payCancel = new PPayRefund();
                String cancelGuid = pPayRefundService.getGuid();
                payCancel.setGuid(cancelGuid);
                payCancel.setDeleteFlg("0");//删除标识 0代表未删除
                payCancel.setCreatedDate(new Date());
                payCancel.setRefundAmount(refundAmount);//撤销金额
                payCancel.setRefundStartTime(String.valueOf(System.currentTimeMillis()));//撤销动作开始时间
                payCancel.setOldTrxid(pPay.getTrxid());//原订单在收银宝的流水号，用于查账，撤销，退款
                payCancel.setPayGuid(requestJson.getPaymentId());//订单guis
                //==================执行交易撤销================
                try {
                    /*
                     * refundAmount 退款金额
                     * reqsn 随机数
                     * pPay.getTrxid() 原交易收银宝平台流水号
                     *oldreqsn	原交易单号	原交易的商户交易单号
                     */
                    Map<String, String> cancel = new TreeMap<>();
                    logger.info("当天撤销请求参数：payCancel" + payCancel.getGuid() + " pPay" + pPay.getTrxid() + " pPayCust" + pPayCust.getCustId());
                    if (FinalUtil.CUP_PAY_TYPE.equals(pPay.getPayType())) {
                        cancel = callOut_tlPublicService.cancelCUP(MyDateUtil.NotString(cancelGuid), Long.valueOf(refundAmount), MyDateUtil.NotString(pPay.getGuid()), pPay.getTrxid(), pPayCust);
                    } else {
                        cancel = callOut_tlPublicService.cancel(Long.valueOf(refundAmount), MyDateUtil.NotString(cancelGuid), pPay.getTrxid(), MyDateUtil.NotString(pPay.getGuid()), pPayCust);
                    }
                    logger.info("当天撤销响应参数" + cancel.toString());
                    if ("SUCCESS".equals(cancel.get(FinalUtil.RETCDE))) {
                        retJson.setErrorMessage(cancel.get(FinalUtil.ERRMSG));
                        retJson.addBody(FinalUtil.TRXSTATUS, cancel.get(FinalUtil.TRXSTATUS));
                        retJson.addBody("trxid", cancel.get("trxid"));
                        retJson.addBody("refoundId",cancelGuid);  //退款id
                        payCancel.setTrxid(cancel.get("trxid"));//交易撤销流水单号
                        payCancel.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(cancel.get("fintime")).getTime()));
                        if ("0000".equals(cancel.get(FinalUtil.TRXSTATUS))) {
                            payCancel.setRefundStatus(FinalUtil.PAY_REFUND_SUCCESS);//退款状态 0表示成功
                        } else {
                            if ("3".equals(cancel.get(FinalUtil.TRXSTATUS).substring(0, 1))) {
                                payCancel.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                            }
                        }
                    } else {
                        //保存交易撤销数据
                        retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE, "FAIL");
                        payCancel.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                    }
                    pPayRefundService.save(payCancel);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.debug("通联异常参数：" + e.getMessage());
                    retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE, e.getMessage());
                }
                //==================交易日期在大于今天小于88天内============
                if (MyDateUtil.getDayDiffFromToday1(pPay.getPayEndTime())) {
                    //================存储退款数据==================
                    logger.info("================请求金额退款开始================");
                    PPayRefund PPayRefund = new PPayRefund();
                    String guid = pPayRefundService.getGuid();
                    PPayRefund.setDeleteFlg("0");//删除标识 0代表未删除
                    pPayRefund.setGuid(guid);
                    PPayRefund.setCreatedDate(new Date());
                    PPayRefund.setRefundAmount(refundAmount);//撤销金额
                    PPayRefund.setRefundStartTime(String.valueOf(System.currentTimeMillis()));//撤销动作开始时间
                    PPayRefund.setOldTrxid(pPay.getTrxid());//原订单在收银宝的流水号，用于查账，撤销，退款
                    PPayRefund.setPayGuid(requestJson.getPaymentId());//订单guis
                    //==================执行退款===============
                    try {
                    /*
                     * refundAmount 退款金额
                     * reqsn 随机数
                     * pPay.getTrxid() 原交易收银宝平台流水号
                     *oldreqsn	原交易单号	原交易的商户交易单号
                     * 支持部分金额退款，隔天交易退款
                     */
                        Map<String, String> refund = new TreeMap<>();
                        logger.info("隔天退款请求参数：PPayRefund" + refundAmount + " pPay" + pPay.getTrxid() + " pPayCust" + pPayCust.getCustId());
                        if (FinalUtil.CUP_PAY_TYPE.equals(pPay.getPayType())) {
                            refund = callOut_tlPublicService.refundCUP(Long.valueOf(refundAmount), MyDateUtil.NotString(guid), MyDateUtil.NotString(pPay.getGuid()), pPay.getTrxid(), pPayCust);
                        } else {
                            refund = callOut_tlPublicService.refund(Long.valueOf(refundAmount), MyDateUtil.NotString(guid), pPay.getTrxid(), MyDateUtil.NotString(pPay.getGuid()), pPayCust);
                        }
                        logger.info("隔天退款响应参数：" + refund.toString());
                        if ("SUCCESS".equals(refund.get(FinalUtil.RETCDE))) {
                            retJson.setErrorMessage(refund.get(FinalUtil.ERRMSG));
                            retJson.addBody(FinalUtil.TRXSTATUS, refund.get(FinalUtil.TRXSTATUS));
                            retJson.addBody("trxid", refund.get("trxid"));
                            PPayRefund.setTrxid(refund.get("trxid"));//交易撤销流水单号
                            retJson.addBody("refoundId",guid);  //退款id
                            if(refund.get("fintime") != null){
                                PPayRefund.setRefundEndTime(String.valueOf(new SimpleDateFormat("yyyyMMddHHmmss").parse(refund.get("fintime")).getTime()));
                            }
                            if ("0000".equals(refund.get(FinalUtil.TRXSTATUS))) {
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_SUCCESS);//退款状态 0表示成功
                            }
                            if ("3".equals(refund.get(FinalUtil.TRXSTATUS).substring(0, 1))) {
                                PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                            }
                        } else {
                            PPayRefund.setRefundStatus(FinalUtil.PAY_REFUND_FAILUE);
                            retJson = new ResponseJson(ErrorInfoEnum.FAIL_REFUND, refund.get("errmsg"));
                        }
                        //保存交易退款数据
                        pPayRefundService.save(PPayRefund);
                    } catch (Exception e) {
                        e.printStackTrace();
                        logger.debug("通联异常参数：" + e.getMessage());
                        retJson = new ResponseJson(ErrorInfoEnum.PAY_RESULT_TYPE, e.getMessage());
                    }
                }

            }
        }
        pPayService.update(pPay);// 更新订单信息
        return retJson.toString();
    }

    /**
     * 根据小区sfid查询通联账户信息
     *
     * @param estateGuid
     * @return
     */
    public PPayCust getTLMessage(String estateGuid, String payType) {
        return pPayCustService.getBySfGuid1(estateGuid, payType);
    }
}

